{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "view-in-github"
   },
   "source": [
    "<a href=\"https://colab.research.google.com/github/CoreTheGreat/HBPU-Machine-Learning-Course/blob/main/ML_Chapter3_Classification.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "lPboLx_o0UxI"
   },
   "source": [
    "# 第五章：深度学习\n",
    "湖北理工学院《机器学习》课程资料\n",
    "\n",
    "作者：李辉楚吴\n",
    "\n",
    "笔记内容概述: 前馈神经网络、全连接网络、手写字母识别"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 按照Classification章节，读取MNIST数据集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 1000
    },
    "id": "sM-ziKb94S9_",
    "outputId": "9a8bd59b-1ed4-47e3-e118-cee1849a610a"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test set size: 10000\n",
      "Training set size: 60000\n",
      "Number of training samples: 43360\n",
      "Number of cross-validation samples: 10850\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "label_size = 18 # Label size\n",
    "ticklabel_size = 14 # Tick label size\n",
    "\n",
    "class FlattenTransform:\n",
    "    def __call__(self, tensor):\n",
    "        ''' \n",
    "        Flatten tensor into an 1-D vector\n",
    "        '''\n",
    "        return tensor.view(-1)\n",
    "    \n",
    "# Define a transform to normalize the data\n",
    "transform = transforms.Compose([\n",
    "    transforms.ToTensor(),\n",
    "    FlattenTransform()\n",
    "])\n",
    "\n",
    "# Load test data from the MNIST\n",
    "testset = torchvision.datasets.MNIST(root='./Data', train=False, download=False, transform=transform)\n",
    "print(f\"Test set size: {len(testset)}\")\n",
    "\n",
    "# Load training data from the MNIST\n",
    "trainset = torchvision.datasets.MNIST(root='./Data', train=True, download=False, transform=transform)\n",
    "print(f\"Training set size: {len(trainset)}\")\n",
    "\n",
    "# Rate of trX and cvX\n",
    "tr_cv_rate = 0.8\n",
    "\n",
    "# Create a list to store indices for each class\n",
    "class_indices = [[] for _ in range(10)]  # 10 classes in MNIST\n",
    "\n",
    "# Populate class_indices\n",
    "for idx, (_, label) in enumerate(trainset):\n",
    "    class_indices[label].append(idx)\n",
    "\n",
    "# Calculate the number of samples for each class in training and validation sets\n",
    "train_size_per_class = int(tr_cv_rate * min(len(indices) for indices in class_indices))\n",
    "val_size_per_class = min(len(indices) for indices in class_indices) - train_size_per_class\n",
    "\n",
    "# Create balanced train and validation sets\n",
    "train_indices = []\n",
    "val_indices = []\n",
    "for indices in class_indices:\n",
    "    train_indices.extend(indices[:train_size_per_class])\n",
    "    val_indices.extend(indices[train_size_per_class:train_size_per_class + val_size_per_class])\n",
    "\n",
    "# Create Subset datasets\n",
    "from torch.utils.data import Subset\n",
    "trX = Subset(trainset, train_indices)\n",
    "cvX = Subset(trainset, val_indices)\n",
    "\n",
    "print(f\"Number of training samples: {len(trX)}\")\n",
    "print(f\"Number of cross-validation samples: {len(cvX)}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "构建DataLoaders，准备训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "BWPSDyOq5qOO",
    "outputId": "9aed06f2-67a9-4a6f-f00c-d91554c3a260"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Input_size is 784\n",
      "tensor([[1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.]])\n"
     ]
    }
   ],
   "source": [
    "batch_size = 42 # Define training batch\n",
    "\n",
    "def one_hot_collate(batch):\n",
    "    data = torch.stack([item[0] for item in batch])\n",
    "    labels = torch.tensor([item[1] for item in batch])\n",
    "    one_hot_labels = torch.zeros(labels.size(0), 10)  # 10 classes in MNIST\n",
    "    one_hot_labels.scatter_(1, labels.unsqueeze(1), 1)\n",
    "    return data, one_hot_labels\n",
    "\n",
    "trLoader = torch.utils.data.DataLoader(trX, batch_size=batch_size, shuffle=True, num_workers=0, collate_fn=one_hot_collate)\n",
    "cvLoader = torch.utils.data.DataLoader(cvX, batch_size=batch_size, shuffle=False, num_workers=0, collate_fn=one_hot_collate)\n",
    "teLoader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False, num_workers=0, collate_fn=one_hot_collate)\n",
    "\n",
    "# Get a batch of training data\n",
    "dataiter = iter(trLoader)\n",
    "data, labels = next(dataiter)\n",
    "\n",
    "input_size = data[0].numpy().shape[0]\n",
    "print(f'Input_size is {input_size}')\n",
    "print(labels)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 定义并训练全连接神经网络\n",
    "* 输入：1-D向量\n",
    "* 输出：手写字母类型的概率分布\n",
    "* 隐藏层：2层\n",
    "* 节点数：100个/层"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "FNN(\n",
      "  (fc1): Linear(in_features=784, out_features=10, bias=True)\n",
      "  (relu1): ReLU()\n",
      "  (fc2): Linear(in_features=10, out_features=10, bias=True)\n",
      "  (relu2): ReLU()\n",
      "  (fc3): Linear(in_features=10, out_features=10, bias=True)\n",
      "  (softmax): Softmax(dim=1)\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "import torch.nn as nn\n",
    "\n",
    "class FNN(nn.Module):\n",
    "    def __init__(self, input_size, hidden_size, num_classes):\n",
    "        super(FNN, self).__init__()\n",
    "        self.fc1 = nn.Linear(input_size, hidden_size)\n",
    "        self.relu1 = nn.ReLU()\n",
    "        self.fc2 = nn.Linear(hidden_size, hidden_size)\n",
    "        self.relu2 = nn.ReLU()\n",
    "        self.fc3 = nn.Linear(hidden_size, num_classes)\n",
    "        self.softmax = nn.Softmax(dim=1)\n",
    "    \n",
    "    def forward(self, x):\n",
    "        x = self.fc1(x)\n",
    "        x = self.relu1(x)\n",
    "        x = self.fc2(x)\n",
    "        x = self.relu2(x)\n",
    "        x = self.fc3(x)\n",
    "        out = self.softmax(x)\n",
    "        return out\n",
    "\n",
    "# Define the model parameters\n",
    "hidden_size = 10\n",
    "num_classes = 10  # MNIST has 10 classes (digits 0-9)\n",
    "\n",
    "# Instantiate the model\n",
    "model = FNN(input_size, hidden_size, num_classes)\n",
    "print(model)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用Adam作为Optimizor训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch [1/50], Train Loss: 1.8045, CV Loss: 1.6680\n",
      "Epoch [2/50], Train Loss: 1.6497, CV Loss: 1.6464\n",
      "Epoch [3/50], Train Loss: 1.6353, CV Loss: 1.6395\n",
      "Epoch [4/50], Train Loss: 1.6277, CV Loss: 1.6352\n",
      "Epoch [5/50], Train Loss: 1.6229, CV Loss: 1.6303\n",
      "Epoch [6/50], Train Loss: 1.6189, CV Loss: 1.6287\n",
      "Epoch [7/50], Train Loss: 1.6158, CV Loss: 1.6256\n",
      "Epoch [8/50], Train Loss: 1.6132, CV Loss: 1.6251\n",
      "Epoch [9/50], Train Loss: 1.6113, CV Loss: 1.6219\n",
      "Epoch [10/50], Train Loss: 1.6098, CV Loss: 1.6216\n",
      "Epoch [11/50], Train Loss: 1.6085, CV Loss: 1.6214\n",
      "Epoch [12/50], Train Loss: 1.6073, CV Loss: 1.6204\n",
      "Epoch [13/50], Train Loss: 1.6061, CV Loss: 1.6203\n",
      "Epoch [14/50], Train Loss: 1.6053, CV Loss: 1.6193\n",
      "Epoch [15/50], Train Loss: 1.6041, CV Loss: 1.6190\n",
      "Epoch [16/50], Train Loss: 1.6039, CV Loss: 1.6183\n",
      "Epoch [17/50], Train Loss: 1.6028, CV Loss: 1.6219\n",
      "Epoch [18/50], Train Loss: 1.6007, CV Loss: 1.5807\n",
      "Epoch [19/50], Train Loss: 1.5435, CV Loss: 1.5530\n",
      "Epoch [20/50], Train Loss: 1.5346, CV Loss: 1.5490\n",
      "Epoch [21/50], Train Loss: 1.5305, CV Loss: 1.5485\n",
      "Epoch [22/50], Train Loss: 1.5276, CV Loss: 1.5455\n",
      "Epoch [23/50], Train Loss: 1.5257, CV Loss: 1.5462\n",
      "Epoch [24/50], Train Loss: 1.5245, CV Loss: 1.5433\n",
      "Epoch [25/50], Train Loss: 1.5225, CV Loss: 1.5438\n",
      "Epoch [26/50], Train Loss: 1.5213, CV Loss: 1.5413\n",
      "Epoch [27/50], Train Loss: 1.5199, CV Loss: 1.5421\n",
      "Epoch [28/50], Train Loss: 1.5194, CV Loss: 1.5403\n",
      "Epoch [29/50], Train Loss: 1.5183, CV Loss: 1.5404\n",
      "Epoch [30/50], Train Loss: 1.5173, CV Loss: 1.5415\n",
      "Epoch [31/50], Train Loss: 1.5170, CV Loss: 1.5396\n",
      "Epoch [32/50], Train Loss: 1.5160, CV Loss: 1.5378\n",
      "Epoch [33/50], Train Loss: 1.5156, CV Loss: 1.5376\n",
      "Epoch [34/50], Train Loss: 1.5147, CV Loss: 1.5367\n",
      "Epoch [35/50], Train Loss: 1.5142, CV Loss: 1.5376\n",
      "Epoch [36/50], Train Loss: 1.5132, CV Loss: 1.5380\n",
      "Epoch [37/50], Train Loss: 1.5129, CV Loss: 1.5414\n",
      "Epoch [38/50], Train Loss: 1.5125, CV Loss: 1.5367\n",
      "Epoch [39/50], Train Loss: 1.5125, CV Loss: 1.5375\n",
      "Epoch [40/50], Train Loss: 1.5121, CV Loss: 1.5382\n",
      "Epoch [41/50], Train Loss: 1.5111, CV Loss: 1.5373\n",
      "Epoch [42/50], Train Loss: 1.5110, CV Loss: 1.5372\n",
      "Epoch [43/50], Train Loss: 1.5105, CV Loss: 1.5364\n",
      "Epoch [44/50], Train Loss: 1.5101, CV Loss: 1.5368\n",
      "Epoch [45/50], Train Loss: 1.5092, CV Loss: 1.5386\n",
      "Epoch [46/50], Train Loss: 1.5098, CV Loss: 1.5364\n",
      "Epoch [47/50], Train Loss: 1.5087, CV Loss: 1.5371\n",
      "Epoch [48/50], Train Loss: 1.5083, CV Loss: 1.5371\n",
      "Epoch [49/50], Train Loss: 1.5088, CV Loss: 1.5352\n",
      "Epoch [50/50], Train Loss: 1.5083, CV Loss: 1.5359\n"
     ]
    }
   ],
   "source": [
    "# Define loss function and optimizer\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "optimizer = torch.optim.Adam(model.parameters())\n",
    "\n",
    "# Lists to store losses\n",
    "train_losses = []\n",
    "cv_losses = []\n",
    "\n",
    "# Number of epochs\n",
    "num_epochs = 50\n",
    "\n",
    "for epoch in range(num_epochs):\n",
    "    model.train()\n",
    "    batch_losses = []\n",
    "    \n",
    "    for batch_x, batch_y in trLoader:\n",
    "        # Forward pass\n",
    "        outputs = model(batch_x)\n",
    "        loss = criterion(outputs, batch_y)\n",
    "        \n",
    "        # Backward pass and optimize\n",
    "        optimizer.zero_grad()\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        \n",
    "        batch_losses.append(loss.item())\n",
    "    \n",
    "    # Calculate average training loss for this epoch\n",
    "    avg_train_loss = sum(batch_losses) / len(batch_losses)\n",
    "    train_losses.append(avg_train_loss)\n",
    "    \n",
    "    # Evaluate on cross-validation set\n",
    "    model.eval()\n",
    "    cv_batch_losses = []\n",
    "    with torch.no_grad():\n",
    "        for cv_x, cv_y in cvLoader:\n",
    "            cv_outputs = model(cv_x)\n",
    "            cv_loss = criterion(cv_outputs, cv_y)\n",
    "            cv_batch_losses.append(cv_loss.item())\n",
    "    \n",
    "    avg_cv_loss = sum(cv_batch_losses) / len(cv_batch_losses)\n",
    "    cv_losses.append(avg_cv_loss)\n",
    "    \n",
    "    print(f'Epoch [{epoch+1}/{num_epochs}], Train Loss: {avg_train_loss:.4f}, CV Loss: {avg_cv_loss:.4f}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "计算识别精度，展示学习曲线"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy on training set: 95.64%\n",
      "Accuracy on cross-validation set: 92.57%\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1cAAAHUCAYAAADWedKvAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAAB/0ElEQVR4nO3dd3gU1cIG8He2Z1M2vZFCCx1Cr9IEaYI0BQVpYsf2YUVFwIbYQC+K16sQUS+gIshV6QiIoIISQECkBBIgISQhPdk63x+zO8mSQvpmk/f3PPPs7JmyZ5KJ7ss5c44giqIIIiIiIiIiqhaFqytARERERETUEDBcERERERER1QCGKyIiIiIiohrAcEVERERERFQDGK6IiIiIiIhqAMMVERERERFRDWC4IiIiIiIiqgEMV0RERERERDWA4YqIiIiIiKgGMFwRUaMhCEKFlt27d1frcxYuXAhBEKp07O7du2ukDvXdzJkz0bRp0wrta7PZ8Pnnn2Po0KEIDAyEWq1GcHAwRo8ejf/973+w2Wy1W9lqOnLkCARBwHPPPVfmPqdPn4YgCHjssccqfN7S7rNBgwZh0KBBNzz2/PnzEAQBcXFxFf48hxMnTmDhwoU4f/58iW2V+b3WNEEQ8Mgjj7jks4mIHFSurgARUV05cOCA0/tXXnkFP/30E3bt2uVU3q5du2p9zr333osRI0ZU6diuXbviwIED1a5DQ1FYWIhx48Zh27ZtuPPOO7FixQqEhobi6tWr2LJlC+644w6sW7cOY8eOdXVVyxQbG4tu3bph9erVeO2116BUKkvss2rVKgDA7Nmzq/VZH374YbWOr4gTJ05g0aJFGDRoUIkgNX/+fDz++OO1XgciovqK4YqIGo3evXs7vQ8KCoJCoShRfr38/Hzo9foKf05ERAQiIiKqVEcfH58b1qcxmTt3LrZu3YrPPvsM06dPd9o2YcIEPP300ygoKCjzeLPZDEEQoFK59n93s2fPxsMPP4zNmzdj9OjRTtusVitWr16Nbt26ITY2tlqf4+pQ3qJFC5d+PhGRq7FbIBFRMYMGDUKHDh2wd+9e9O3bF3q9Hvfccw8AYN26dRg2bBjCwsLg4eGBtm3b4rnnnkNeXp7TOUrrrtW0aVOMHj0aW7ZsQdeuXeHh4YE2bdpg5cqVTvuV1i1w5syZ8PLywpkzZzBq1Ch4eXkhMjISTz75JIxGo9PxFy9exO233w5vb2/4+vpi6tSpOHjwYIW6gF29ehUPP/ww2rVrBy8vLwQHB+Pmm2/Gzz//7LSfo0vZ22+/jXfffRfNmjWDl5cX+vTpg19//bXEeePi4tC6dWtotVq0bdsWq1evLrceDikpKfjkk08wfPjwEsHKISYmBp06dQJQ9LP7/PPP8eSTT6JJkybQarU4c+YMAGDlypWIjY2FTqeDv78/xo8fj5MnTzqd79y5c7jzzjsRHh4OrVaLkJAQDBkyBPHx8fI+u3btwqBBgxAQEAAPDw9ERUVh4sSJyM/PL/NapkyZAg8PD7mFqrht27bh0qVLlb7PSlNat8DLly9j0qRJ8Pb2hsFgwOTJk5GSklLi2EOHDuHOO+9E06ZN4eHhgaZNm+Kuu+7ChQsX5H3i4uJwxx13AAAGDx4sd6V13FuldQssLCzEvHnz0KxZM2g0GjRp0gRz5sxBZmam034V/RupjoyMDDz88MNo0qQJNBoNmjdvjhdeeKHE39HXX3+NXr16wWAwQK/Xo3nz5vLvB5C6qr766qto3bo1PDw84Ovri06dOuG9996rsboSkXtiyxUR0XWSk5Nx991345lnnsHrr78OhUL6d6jTp09j1KhReOKJJ+Dp6Ym///4bS5Yswe+//16ia2Fpjhw5gieffBLPPfccQkJC8Mknn2D27Nlo2bIlBgwYUO6xZrMZt912G2bPno0nn3wSe/fuxSuvvAKDwYCXXnoJAJCXl4fBgwcjIyMDS5YsQcuWLbFlyxZMnjy5QtedkZEBAFiwYAFCQ0ORm5uLDRs2YNCgQdi5c2eJL+0ffPAB2rRpg2XLlgGQuoSNGjUKCQkJMBgMAKQv47NmzcLYsWPxzjvvICsrCwsXLoTRaJR/rmX56aefYDabMW7cuArV32HevHno06cPPvroIygUCgQHB2Px4sV4/vnncdddd2Hx4sVIT0/HwoUL0adPHxw8eBAxMTEAgFGjRsFqteLNN99EVFQU0tLSsH//fjkInD9/Hrfeeiv69++PlStXwtfXF5cuXcKWLVtgMpnKbOE0GAyYOHEi1q1bh6tXryIoKEjetmrVKuh0OkyZMgVA9e+z4goKCjB06FBcvnwZixcvRqtWrfDDDz+Uek+cP38erVu3xp133gl/f38kJydjxYoV6NGjB06cOIHAwEDceuuteP311/H888/jgw8+QNeuXQGU3WIliiLGjRuHnTt3Yt68eejfvz+OHj2KBQsW4MCBAzhw4AC0Wq28f3X+Rm6ksLAQgwcPxtmzZ7Fo0SJ06tQJP//8MxYvXoz4+Hj88MMPAKTuw5MnT8bkyZOxcOFC6HQ6XLhwweln/+abb2LhwoV48cUXMWDAAJjNZvz9998lAiMRNUIiEVEjNWPGDNHT09OpbODAgSIAcefOneUea7PZRLPZLO7Zs0cEIB45ckTetmDBAvH6/7xGR0eLOp1OvHDhglxWUFAg+vv7iw888IBc9tNPP4kAxJ9++smpngDEr776yumco0aNElu3bi2//+CDD0QA4ubNm532e+CBB0QA4qpVq8q9putZLBbRbDaLQ4YMEcePHy+XJyQkiADEjh07ihaLRS7//fffRQDimjVrRFEURavVKoaHh4tdu3YVbTabvN/58+dFtVotRkdHl/v5b7zxhghA3LJlS4Xq6/jZDRgwwKn82rVrooeHhzhq1Cin8sTERFGr1YpTpkwRRVEU09LSRADismXLyvyMb775RgQgxsfHV6hOpdXv3XfflcvS09NFrVYrTp06tdRjKnufDRw4UBw4cKD8fsWKFSIA8bvvvnPa77777rvhPWGxWMTc3FzR09NTfO+99+Tyr7/+usQ96jBjxgyn3+uWLVtEAOKbb77ptN+6detEAOLHH38sl1X0b6QsAMQ5c+aUuf2jjz4q9e9oyZIlIgBx27ZtoiiK4ttvvy0CEDMzM8s81+jRo8XOnTvfsE5E1PiwWyAR0XX8/Pxw8803lyg/d+4cpkyZgtDQUCiVSqjVagwcOBAASnQvK03nzp0RFRUlv9fpdGjVqpVTt6uyCIKAMWPGOJV16tTJ6dg9e/bA29u7xGAad9111w3P7/DRRx+ha9eu0Ol0UKlUUKvV2LlzZ6nXd+uttzoNzuDonueo06lTp3D58mVMmTLFqZtkdHQ0+vbtW+E6VdbEiROd3h84cAAFBQWYOXOmU3lkZCRuvvlm7Ny5EwDg7++PFi1a4K233sK7776Lw4cPlxiJsHPnztBoNLj//vvx2Wef4dy5cyU+32q1wmKxyIvjHAMHDkSLFi2cugZ++eWXMBqNTl3OqnufFffTTz/B29sbt912m1O5o5WsuNzcXDz77LNo2bIlVCoVVCoVvLy8kJeXV+nPdXC09lz/s7/jjjvg6ekp/+wdqvM3UpG6eHp64vbbb3cqd9TNUZcePXoAACZNmoSvvvoKly5dKnGunj174siRI3j44YexdetWZGdnV7t+RNQwMFwREV0nLCysRFlubi769++P3377Da+++ip2796NgwcP4ttvvwWAcgdVcAgICChRptVqK3SsXq+HTqcrcWxhYaH8Pj09HSEhISWOLa2sNO+++y4eeugh9OrVC+vXr8evv/6KgwcPYsSIEaXW8frrcXTvcuybnp4OAAgNDS1xbGll13N8yU5ISKhQ/R2u//056lHa7zU8PFzeLggCdu7cieHDh+PNN99E165dERQUhMceeww5OTkApO5vO3bsQHBwMObMmYMWLVqgRYsWTs/aDBkyBGq1Wl4cwUkQBNxzzz04duwYDh06BEDqEtisWTMMHjwYQM3cZ9dfe2m//9J+/lOmTMHy5ctx7733YuvWrfj9999x8OBBBAUFVfpzi3++SqVy6gYJSD+L0NBQ+WfvUJ2/kYrUJTQ0tMTzkMHBwVCpVHJdBgwYgI0bN8JisWD69OmIiIhAhw4dsGbNGvmYefPm4e2338avv/6KkSNHIiAgAEOGDJF/r0TUePGZKyKi65Q2R9WuXbtw+fJl7N69W25FAFCvnrEICAjA77//XqK8tMELSvPFF19g0KBBWLFihVO5I1hUpT5lfX5F6jR48GCo1Wps3LgRDz74YIU/9/rfn6MeycnJJfa9fPkyAgMD5ffR0dH49NNPAQD//PMPvvrqKyxcuBAmkwkfffQRAKB///7o378/rFYrDh06hH/961944oknEBISgjvvvBP//ve/nX5mxc8/c+ZMvPTSS1i5ciXUajUOHz6MV155Ra5zTd9nFb0nsrKy8P3332PBggVO83EZjUb5Wbyqfr7FYinxnJkoikhJSZFbiepCQEAAfvvtN4ii6HSPpKamwmKxOP2exo4di7Fjx8JoNOLXX3/F4sWLMWXKFDRt2hR9+vSBSqXC3LlzMXfuXGRmZmLHjh14/vnnMXz4cCQlJVVqdFEialjYckVEVAGOL2PFH74HgH//+9+uqE6pBg4ciJycHGzevNmpfO3atRU6XhCEEtd39OjREvODVVTr1q0RFhaGNWvWQBRFufzChQvYv3//DY8PDQ2VW1HKGmHw7NmzOHr0aLnn6dOnDzw8PPDFF184lV+8eBG7du3CkCFDSj2uVatWePHFF9GxY0f8+eefJbYrlUr06tULH3zwAQDI+7Ru3Rrdu3eXl+Kj54WHh2PEiBFYs2YNPvjgAygUCsyYMUPeXtP32eDBg5GTk4NNmzY5lf/3v/91ei8IAkRRLPG5n3zyCaxWq1PZ9S2U5XH8bK//2a9fvx55eXll/uxrw5AhQ5Cbm4uNGzc6lTvurdLqotVqMXDgQCxZsgQAcPjw4RL7+Pr64vbbb8ecOXOQkZFR6uTKRNR4sOWKiKgC+vbtCz8/Pzz44INYsGAB1Go1vvzySxw5csTVVZPNmDEDS5cuxd13341XX30VLVu2xObNm7F161YAuOHofKNHj8Yrr7yCBQsWYODAgTh16hRefvllNGvWDBaLpdL1USgUeOWVV3Dvvfdi/PjxuO+++5CZmYmFCxdWqFsgIHVVPHfuHGbOnImtW7di/PjxCAkJQVpaGrZv345Vq1Zh7dq18vNepfH19cX8+fPx/PPPY/r06bjrrruQnp6ORYsWQafTYcGCBQCkIPnII4/gjjvuQExMDDQaDXbt2oWjR4/KrTkfffQRdu3ahVtvvRVRUVEoLCyUhwofOnRoha5p9uzZ+OGHH+Rh5iMjI+VtNX2fTZ8+HUuXLsX06dPx2muvISYmBj/++KN8Tzj4+PhgwIABeOuttxAYGIimTZtiz549+PTTT+Hr6+u0b4cOHQAAH3/8Mby9vaHT6dCsWbNSu/TdcsstGD58OJ599llkZ2ejX79+8miBXbp0wbRp06p0XWU5e/YsvvnmmxLl7dq1w/Tp0/HBBx9gxowZOH/+PDp27Ih9+/bh9ddfx6hRo+Tf30svvYSLFy9iyJAhiIiIQGZmJt577z2nZ9/GjBmDDh06oHv37ggKCsKFCxewbNkyREdHyyNPElEj5drxNIiIXKes0QLbt29f6v779+8X+/TpI+r1ejEoKEi89957xT///LPEqGtljRZ46623ljjn9aO7lTVa4PX1LOtzEhMTxQkTJoheXl6it7e3OHHiRPHHH38sdcS46xmNRvGpp54SmzRpIup0OrFr167ixo0bS4wA5xgt8K233ipxDgDiggULnMo++eQTMSYmRtRoNGKrVq3ElStXljhneSwWi/jZZ5+JN998s+jv7y+qVCoxKChIHDlypPjf//5XtFqtoigW/ey+/vrrUs/zySefiJ06dRI1Go1oMBjEsWPHisePH5e3X7lyRZw5c6bYpk0b0dPTU/Ty8hI7deokLl26VB4V8cCBA+L48ePF6OhoUavVigEBAeLAgQPFTZs2VehaRFEUTSaTGBISUurIdaJYvfvs+vtJFEXx4sWL4sSJE53uif3795c4n2M/Pz8/0dvbWxwxYoT4119/idHR0eKMGTOczrls2TKxWbNmolKpdDpPab/XgoIC8dlnnxWjo6NFtVothoWFiQ899JB47do1p/0q+jdSFgBlLo57Mj09XXzwwQfFsLAwUaVSidHR0eK8efPEwsJC+Tzff/+9OHLkSLFJkyaiRqMRg4ODxVGjRok///yzvM8777wj9u3bVwwMDBQ1Go0YFRUlzp49Wzx//vwN60lEDZsgisX6ahARUYPz+uuv48UXX0RiYiIiIiJcXR0iIqIGi90CiYgakOXLlwMA2rRpA7PZjF27duH999/H3XffzWBFRERUyxiuiIgaEL1ej6VLl+L8+fMwGo2IiorCs88+ixdffNHVVSMiImrw2C2QiIiIiIioBnAodiIiIiIiohrAcEVERERERFQDGK6IiIiIiIhqAAe0KIXNZsPly5fh7e0NQRBcXR0iIiIiInIRURSRk5OD8PBwKBTlt00xXJXi8uXLiIyMdHU1iIiIiIionkhKSrrhtCYMV6Xw9vYGIP0AfXx8XFwbIiIiIiJylezsbERGRsoZoTwMV6VwdAX08fFhuCIiIiIiogo9LsQBLYiIiIiIiGoAwxUREREREVENYLgiIiIiIiKqAXzmioiIiKiRE0URFosFVqvV1VUhcgm1Wg2lUlnt8zBcERERETViJpMJycnJyM/Pd3VViFxGEARERETAy8urWudhuCIiIiJqpGw2GxISEqBUKhEeHg6NRlOhEdGIGhJRFHH16lVcvHgRMTEx1WrBYrgiIiIiaqRMJhNsNhsiIyOh1+tdXR0ilwkKCsL58+dhNpurFa44oAURERFRI6dQ8CshNW411WLLvyQiIiIiIqIawHBFRERERERUAxiuiIiIiKjRGzRoEJ544okK73/+/HkIgoD4+PhaqxO5H4YrIiIiInIbgiCUu8ycObNK5/3222/xyiuvVHj/yMhIJCcno0OHDlX6vIpiiHMvHC2QiIiIiNxGcnKyvL5u3Tq89NJLOHXqlFzm4eHhtL/ZbIZarb7hef39/StVD6VSidDQ0EodQw0fW67quf/sPYfhS/fik5/PuboqRERE1MCJooh8k8UliyiKFapjaGiovBgMBgiCIL8vLCyEr68vvvrqKwwaNAg6nQ5ffPEF0tPTcddddyEiIgJ6vR4dO3bEmjVrnM57fbfApk2b4vXXX8c999wDb29vREVF4eOPP5a3X9+itHv3bgiCgJ07d6J79+7Q6/Xo27evU/ADgFdffRXBwcHw9vbGvffei+eeew6dO3eu0u8LAIxGIx577DEEBwdDp9PhpptuwsGDB+Xt165dw9SpUxEUFAQPDw/ExMRg1apVAKSh+B955BGEhYVBp9OhadOmWLx4cZXrQmy5qvcyC0w4dSUHF68VuLoqRERE1MAVmK1o99JWl3z2iZeHQ6+pma+mzz77LN555x2sWrUKWq0WhYWF6NatG5599ln4+Pjghx9+wLRp09C8eXP06tWrzPO88847eOWVV/D888/jm2++wUMPPYQBAwagTZs2ZR7zwgsv4J133kFQUBAefPBB3HPPPfjll18AAF9++SVee+01fPjhh+jXrx/Wrl2Ld955B82aNavytT7zzDNYv349PvvsM0RHR+PNN9/E8OHDcebMGfj7+2P+/Pk4ceIENm/ejMDAQJw5cwYFBdL3yvfffx+bNm3CV199haioKCQlJSEpKanKdSGGq3rPT68BAGTkmVxcEyIiIiL38MQTT2DChAlOZU899ZS8/uijj2LLli34+uuvyw1Xo0aNwsMPPwxACmxLly7F7t27yw1Xr732GgYOHAgAeO6553DrrbeisLAQOp0O//rXvzB79mzMmjULAPDSSy9h27ZtyM3NrdJ15uXlYcWKFYiLi8PIkSMBAP/5z3+wfft2fPrpp3j66aeRmJiILl26oHv37gCkFjmHxMRExMTE4KabboIgCIiOjq5SPaiIS8PV3r178dZbb+GPP/5AcnIyNmzYgHHjxpV7zJdffok333wTp0+fhsFgwIgRI/D2228jICBA3mf9+vWYP38+zp49ixYtWuC1117D+PHja/lqaoe/pxSuruUzXBEREVHt8lArceLl4S777JriCBIOVqsVb7zxBtatW4dLly7BaDTCaDTC09Oz3PN06tRJXnd0P0xNTa3wMWFhYQCA1NRUREVF4dSpU3JYc+jZsyd27dpVoeu63tmzZ2E2m9GvXz+5TK1Wo2fPnjh58iQA4KGHHsLEiRPx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7RpmzZrltJ8gCAgNDa2xetY3cssVuwUSEREREdUbbv3M1aeffoqhQ4ciOjraqTw3NxfR0dGIiIjA6NGjcfjw4XLPYzQakZ2d7bTUZ45wlZFndnFNiIiIiIjIwW3DVXJyMjZv3ox7773XqbxNmzaIi4vDpk2bsGbNGuh0OvTr1w+nT58u81yLFy+WW8UMBgMiIyNru/rV4sdnroiIiIiI6h23DVdxcXHw9fXFuHHjnMp79+6Nu+++G7Gxsejfvz+++uortGrVCv/617/KPNe8efOQlZUlL0lJSbVc++qRh2Jnt0AiIiIionrDpc9cVZUoili5ciWmTZsGjUZT7r4KhQI9evQot+VKq9VCq9XWdDVrjZ+nGgAHtCAiIiIiqk/csuVqz549OHPmDGbPnn3DfUVRRHx8PMLCwuqgZnWDQ7ETEREREdU/Lm25ys3NxZkzZ+T3CQkJiI+Ph7+/P6KiojBv3jxcunQJq1evdjru008/Ra9evdChQ4cS51y0aBF69+6NmJgYZGdn4/3330d8fDw++OCDWr+euuLoFngt3wSbTYRCIbi4RkRERERE5NJwdejQIQwePFh+P3fuXADAjBkzEBcXh+TkZCQmJjodk5WVhfXr1+O9994r9ZyZmZm4//77kZKSAoPBgC5dumDv3r3o2bNn7V1IHfO1hyubCGQXmuX3RERERETkOoIoiqKrK1HfZGdnw2AwICsrCz4+Pq6uTqk6LtiKHKMFu54ciOZBXq6uDhERERFRg1SZbOCWz1xRseHYOWIgEREREVG9wHDlpjiRMBERERFR/cJw5aY4YiARERERUf3CcOWm/DiRMBERERFRvcJw5ab8OZEwEREREVG9wnDlpvzkZ64YroiIiIiI6gOGKzclTyTMcEVEREREVC8wXLkpueWKz1wREREREdULDFduiqMFEhERERHVLwxXbkoeLZDhioiIiIioXmC4clMB9par7EILzFabi2tDREREREQMV27Kx0MNhSCtZ+abXVsZIiIiIiJiuHJXSoUAX3YNJCIiIiKqNxiu3JifnhMJExERERHVFwxXbkweMZDDsRMRERERuRzDlRvjiIFERERERPUHw5Ub41xXRERERET1B8OVG/Ozh6sMdgskIiIiInI5his35q9nyxURERERUX3BcOXG/OWWK85zRURERETkagxXbozPXBERERER1R8MV25MfuaK4YqIiIiIyOUYrtyYP4diJyIiIiKqNxiu3JifpxoAUGC2osBkdXFtiIiIiIgaN4YrN+alVUGtFAAA1zgcOxERERGRSzFcuTFBEODHroFERERERPUCw5Wbk0cMZMsVEREREZFLMVy5ObZcERERERHVDwxXbs7fi3NdERERERHVBwxXbo7DsRMRERER1Q8MV25OnkiYz1wREREREbkUw5Wb89dLc11dyzO7uCZERERERI0bw5Wbk1uu2C2QiIiIiMilGK7cHIdiJyIiIiKqHxiu3ByHYiciIiIiqh8Yrtxc8ZYrURRdXBsiIiIiosaL4crNOcKV2Soi12hxcW2IiIiIiBovhis3p1MrodcoAXDEQCIiIiIiV2K4agAcz12l5xldXBMiIiIiosaL4aoB4IiBRERERESux3DVABTNdcVugURERERErsJw1QD469UAgGscjp2IiIiIyGUYrhoAueWK3QKJiIiIiFyG4aoB8LcPaMGWKyIiIiIi12G4agCKnrliuCIiIiIichWGqwYggKMFEhERERG5HMNVA+BouUpnyxURERERkcswXDUA8jxXDFdERERERC7j0nC1d+9ejBkzBuHh4RAEARs3bix3/5kzZ0IQhBJL+/btnfZbv3492rVrB61Wi3bt2mHDhg21eBWu52cf0CKzwAyrTXRxbYiIiIiIGieXhqu8vDzExsZi+fLlFdr/vffeQ3JysrwkJSXB398fd9xxh7zPgQMHMHnyZEybNg1HjhzBtGnTMGnSJPz222+1dRku52uf50oUgawCTiRMREREROQKgiiK9aKpQxAEbNiwAePGjavwMRs3bsSECROQkJCA6OhoAMDkyZORnZ2NzZs3y/uNGDECfn5+WLNmTYXOm52dDYPBgKysLPj4+FTqOlyl08KtyC60YMfcgWgZ7OXq6hARERERNQiVyQZu/czVp59+iqFDh8rBCpBaroYNG+a03/Dhw7F///4yz2M0GpGdne20uBt/jhhIRERERORSbhuukpOTsXnzZtx7771O5SkpKQgJCXEqCwkJQUpKSpnnWrx4MQwGg7xERkbWSp1rE+e6IiIiIiJyLbcNV3FxcfD19S21G6EgCE7vRVEsUVbcvHnzkJWVJS9JSUk1Xd1a56/niIFERERERK6kcnUFqkIURaxcuRLTpk2DRqNx2hYaGlqilSo1NbVE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dNO7EUEQAACiKMrrpe3j4eFRofOp1eoSx9pstkrViYiI3AufuSIiokbn119/LfG+TZs2AIB27dohPj4eeXl58vZffvkFCoUCrVq1gre3N5o2bYqdO3fWaZ2JiKj+Y8sVERE1OEajESkpKU5lKpUKgYGBAICvv/4a3bt3x0033YQvv/wSv//+Oz799FMAwNSpU7FgwQLMmDEDCxcuxNWrV/Hoo49i2rRpCAkJAQAsXLgQDz74IIKDgzFy5Ejk5OTgl19+waOPPlq3F0pERPUKwxURETU4W7ZsQVhYmFNZ69at8ffffwOQRvJbu3YtHn74YYSGhuLLL79Eu3btAAB6vR5bt27F448/jh49ekCv12PixIl499135XPNmDEDhYWFWLp0KZ566ikEBgbi9ttvr7sLJCKieomjBRIRUaMiCAI2bNiAcePGuboqRETUwPCZKyIiIiIiohrAcEVERERERFQD+MwVERE1KuwNT0REtYUtV0RERERERDWA4YqIiIiIiKgGMFwRERERERHVAIYrIiIiIiKiGsBwRUREREREVAMYroiIiIiIiGoAwxUREREREVENYLgiIiIiIiKqAf8PNyryWDU7g18AAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 1000x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Calculate and print accuracies for training and cross-validation sets\n",
    "model.eval()\n",
    "with torch.no_grad():\n",
    "    # Training set accuracy\n",
    "    tr_correct = 0\n",
    "    tr_total = 0\n",
    "    for images, labels in trLoader:\n",
    "        outputs = model(images)\n",
    "        _, predicted = torch.max(outputs, 1)\n",
    "        _, true_labels = torch.max(labels, 1)\n",
    "        tr_total += labels.size(0)\n",
    "        tr_correct += (predicted == true_labels).sum().item()\n",
    "    \n",
    "    tr_accuracy = 100 * tr_correct / tr_total\n",
    "    \n",
    "    # Cross-validation set accuracy\n",
    "    cv_correct = 0\n",
    "    cv_total = 0\n",
    "    for images, labels in cvLoader:\n",
    "        outputs = model(images)\n",
    "        _, predicted = torch.max(outputs, 1)\n",
    "        _, true_labels = torch.max(labels, 1)\n",
    "        cv_total += labels.size(0)\n",
    "        cv_correct += (predicted == true_labels).sum().item()\n",
    "    \n",
    "    cv_accuracy = 100 * cv_correct / cv_total\n",
    "\n",
    "print(f'Accuracy on training set: {tr_accuracy:.2f}%')\n",
    "print(f'Accuracy on cross-validation set: {cv_accuracy:.2f}%')\n",
    "\n",
    "# Plot training and cross-validation losses\n",
    "plt.figure(figsize=(10, 5))\n",
    "plt.plot(range(1, num_epochs+1), train_losses, label='Training Loss')\n",
    "plt.plot(range(1, num_epochs+1), cv_losses, label='Cross-Validation Loss')\n",
    "plt.xlabel('Epoch')\n",
    "plt.ylabel('Loss')\n",
    "plt.title('Training and Cross-Validation Loss')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "colab": {
   "authorship_tag": "ABX9TyO5gS9/MePw+FDiXJA07L6y",
   "include_colab_link": true,
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
